1. Field of the Invention
This invention relates generally to multi-tasking virtual machines and more particularly to supporting per-program classpaths with class sharing in a multi-tasking virtual machine.
2. Description of the Related Art
Modern programming object-oriented languages (like C# or the Java programming language) are typically compiled into an architecture neutral binary format specific to a managed runtime environment (MRE). The Java Virtual Machine (JVM) and .NET exemplify two popular MREs.
MREs typically load an architecture neutral binary image of a program (on-demand and on a per-class basis) and transform these class images at runtime into native representations optimized for the platform where the MRE runs. Such runtime transformations of programs enhance mobility and program portability, but can result in poor memory usage and slow program startup when compared to more conventional programming language runtime architectures.
Both problems originate, to a large extent, from a lack of sharing of the runtime representation of classes across running programs: a substantial amount of program execution is spent loading, verifying and transforming the binary image of classes into platform-dependent native code. The result of these transformations is typically no re-used across serial or simultaneous program executions, resulting in duplication of effort (code transformation, runtime compilation) and memory waste.
Class loaders are a mechanism for dynamically loading software components, such as classes, in a program. Classes are distributed using an architecturally neutral binary representation generally referred to as a class file. Each class may be represented by a single class file, such as may be produced by a Java compiler. Class files may be stored in actual file, in a memory buffer, or obtained from a network stream. In a program, a class type may be uniquely identified by a class name and a namespace. Thus, two classes with the same name may be defined in different namespaces and may be treated as different types. Even through two classes may have the same name, they may be defined in different class files and thus by complete unrelated functionally. Virtual machines frequently implement namespaces as class loaders. Class loaders are generally used by virtual machines to obtain the class files necessary to create the class types needed by a program.
The primordial or boot loader is a build-in class loader used to load the base classes that are intimately associated with a JVM implementation and are essential to its functioning (such as classes of the java.lang.* packages). Every program has a boot loader. The boot loader always retrieves the binary representation of classes from the same location. Further, the boot loader never delegates the resolution of symbolic references. Thus, symbolic references from classes defined by the primordial loader always resolve to the same binary representations (which for a given installation of the JVM never change), and therefore, to the same runtime representations.
The extension and system loaders are two other built-in loaders. As with the boot loader, every program has a single instance of each. The extension loader defines extension classes, i.e. classes that use the Java Extension mechanism. These are frequently bundled as .jar files located in the extensions directory. Extension loaders generally systematically delegate class definition to the boot loader and only attempts to define classes that the boot loader failed to define. In this case, the extension loader searches a class definition in the extension directory. This behavior is predictable and symbolic references from classes defined by the extension loaders always resolve identically for different tasks if the content of the extension directory seen by these tasks is the same (i.e. the same jar files).
The system loader is the default loader that defines classes of user programs. A user-specified classpath is used to locate program classes. The classpath specifies a list of directories, JAR archives, and ZIP archives that contain class files. The behavior of the system loader is generally controlled by the JVM and predictable for a given class path. The system loader always delegates the definition of a class to the extension loader and only attempts to define the class if the extension loader has failed to do so. In this case, the system loader searches for a definition of the class in the sources listed in the classpath.
Managed runtime environments (MREs) generally don't support code sharing well (in particular, sharing of the runtime representation of classes), which frequently results in poor startup performance and large memory footprint of programs. Solutions that have been proposed to share the runtime representation of classes across programs to minimize this problem are generally limited to classes bundled with the MRE itself (e.g. core classes that are part of the standard library of the Java platform).